# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from html_table_parser import parser_functions as parse
import re
import pymysql
from common import *
from conf import Conf
from collections import Counter
class Keyvaluetable():
    def __init__(self,**params):
        self.html = params['html']
        conf = params['conf']
        self.config_dict = conf['all_dict']
        self.super_dict = conf['super_dict']
        self.contact_list = ['电话','联系电话','传真','电子邮箱','联系人','联系人邮箱','邮政编码','邮编','电子邮箱','地址','联系方式','名称','姓名','联系人姓名']
        self.teshu_list = ['单位名称','名称','姓名']

    def read_html_table(self, value):
        result = {}
        tables = BeautifulSoup(value, "lxml").findAll('table')
        for idx, v in enumerate(tables):
            if v.findParent('table') is None:
                result[idx] = parse.make2d(v)
        return result


    # 根据关键字获取表格内相应的数据 v1.1
    def obtain_html_tablev(self,key,result):
        key_listv = {}
        key_list = []
        key_name = ''
        ls = list(self.super_dict.keys())

        for num,i in enumerate(result):
            if key_listv != {}:
                key_list.append(key_listv)
                key_listv = {}

            if len(result[num]) != 0:
                max_len = max((len(l) for l in result[num]))
                # 把list长度统一 预防表格嵌套长度不一致导致数组超出下限
                result[num] = list(map(lambda l: l + ['△'] * (max_len - len(l)), result[num]))

            for numy,x in enumerate(i): # numy : 纵向坐标
                # 用于判断当行关键字不重复
                h_key_list = []
                # 预防某一个关键字同行出现多次导致提取不准确
                s_h = 0
                # 同行出现相同关键字 判断两个关键字是否是一样的
                identical = False
                for numx,j in enumerate(x): # numx : 横向坐标
                    max_numx = len(x)
                    max_numy = len(i)
                    key_name = result[num][numy][numx] # 当前正在处理的关键字
                    # 判断当前数据是否属于特殊处理
                    is_handle = self.is_handle_d(key_name)
                    if len(is_handle) != 0:
                        key,result = self.special_treatment(key,key_name,result,num,numx,numy,is_handle,max_numx,max_numy)

                    if key_name in key:
                        # 同行出现相同关键字 判断两个关键字是否是一样的
                        if identical:
                            if result[num][numy][numx - 1] == result[num][numy][numx]:
                                if result[num][numy + 1][numx - 1] in key:
                                    identical = False
                                    continue
                        identical = False

                        # 判断当前key是否需要特殊处理
                        if key_name in self.teshu_list:
                            zz = self.teshu_value(key,key_name,result,num,numx,numy,max_numx,max_numy)
                            if zz != False:
                                key_name = zz
                                if key_name not in key_listv:
                                    key_listv[key_name] = []
                                key[key_name] = []
                                key[key_name].append(key_name)

                        # 如果这个关键字在此行已经出现过就不进行二次处理
                        if key_name in h_key_list:
                            s_h += 1
                            continue
                        if key_name not in key_listv:
                            key_listv[key_name] = []

                        # 联系方式等特殊处理判断
                        if numy - 1 >= 0:
                            if key_name in self.contact_list:
                                zz = self.contact_value1(key,key_name,key_listv,result,num,numx,numy)
                                if zz != False:
                                    key_name = zz
                                    key_listv[key_name] = []
                                    key[key_name] = []
                                    key[key_name].append(key_name)
                                    result[num][numy][numx] = zz


                        # 是否向右判断
                        if numx + 1 < max_numx: # 预防数组超出下限 确定横向坐标+1不会超出
                            if result[num][numy][numx+1] not in key and result[num][numy][numx+1] != '△':
                                # 组成:'原值':[value,坐标X+1,坐标Y,替换值]
                                key_listv[key_name].append([result[num][numy][numx+1],numx+1,numy,key[key_name][0]])
                                # 横向坐标+1数据跟当前坐标一致
                                if result[num][numy][numx+1] == result[num][numy][numx]:
                                    h_key_list.append(key_name)
                                continue
                            if numx + 2 < max_numx:# 预防数组超出下限 确定横向坐标+2不会超出
                                zz = self.right_value1(key,key_name,key_listv,result,num,max_numx,numx,numy)
                                if zz != False:
                                    key_listv = zz
                                    # 横向坐标+1数据跟当前坐标一致
                                    if result[num][numy][numx + 1] == result[num][numy][numx]:
                                        h_key_list.append(key_name)
                                    continue


                        # 是否向下判断
                        if numy + 1 < max_numy: # 预防数组超出下限 确定纵向坐标+1不会超出
                            if numx < len(result[num][numy+1]): # 预防数组超出下限 确定横向坐标+1不会超出
                                # 当前单元格向下一个单元格内数据不是关键字
                                if result[num][numy+1][numx] not in key:
                                    # 满足向下获取条件
                                    if numx + 1 < max_numx:
                                        # 横向坐标+1数据跟当前坐标一致
                                        if result[num][numy][numx + 1] == result[num][numy][numx]:
                                            h_key_list.append(key_name)
                                    key_listv = self.portrait_value2(key, key_name, key_listv, result, num, i, numx, numy,s_h)

                                # 当前单元格向下一个单元格内数据是关键字 处理同行分割出现多个相同关键字
                                else:
                                    identical = True


        if len(key_list) != len(result):
            key_list.append(key_listv)

        is_key = {}
        is_key['a'] = key['a']
        is_key['b'] = []

        for i in key['b']:
            if i not in is_key['a']:
                is_key['b'].append(i)

        is_key['b'] = list(set(is_key['b']))


        for num,i in enumerate(key_list):
            tt_dict = key_list[num].copy()
            for j in key_list[num]:
                if key_list[num][j] == []:
                    del tt_dict[j]
            key_list[num] = tt_dict

        return key_list,is_key

    # 处理当前关键字是否是特殊字段
    def is_handle_d(self,key_name):
        is_handle = []
        ls = list(self.super_dict.keys())
        for i in ls:
            if i in key_name:
                is_handle.append({'key_name':key_name,'super_key':i})
        return is_handle

    # 特殊字段
    # 处理规则
    def special_treatment(self,key,key_name,result,num,numx,numy,is_handle,max_numx,max_numy):
        is_to = False
        to = []
        # 像右
        for i in is_handle:
            x = numx
            y = numy + 1
            while True:
                if x >= max_numx:
                    break
                if y >= max_numy:
                    break
                if result[num][y][x] in key:
                    if result[num][y][x] in self.super_dict[i['super_key']]:
                        if result[num][y][x] != result[num][y][x-1]:
                            to.append(result[num][y][x])
                        is_to = True
                    else:
                        is_to = False
                else:
                    if len(to) != len(self.super_dict[i['super_key']]):
                        is_to = False
                    break
                x += 1

            x = numx
            y = numy + 1
            if is_to:
                while True:
                    if x >= max_numx:
                        break
                    if result[num][y][x] in self.super_dict[i['super_key']]:
                        result[num][y][x] = key_name + '※' + result[num][y][x]
                        key[result[num][y][x]] = []
                        key[result[num][y][x]].append(result[num][y][x])
                    else:
                        break
                    x += 1



            is_to = False
            to = []
            # 向下
            x = numx
            y = numy
            while True:
                y += 1
                if y >= max_numy:
                    break
                if result[num][y][numx] in key and result[num][y][numx] in self.super_dict[i['super_key']]:
                    if result[num][y][numx] != result[num][y-1][numx]:
                        to.append(result[num][y][x])
                    is_to = True
                else:
                    if len(to) != len(self.super_dict[i['super_key']]):
                        is_to = False
                    break

            x = numx
            y = numy + 1
            if is_to:
                while True:
                    if y >= max_numy:
                        break
                    if result[num][y][numx] in self.super_dict[i['super_key']]:
                        result[num][y][numx] = key_name +'※'+ result[num][y][numx]
                        key[result[num][y][numx]] = []
                        key[result[num][y][numx]].append(result[num][y][numx])
                    else:
                        break
                    y += 1

        return key,result

    # 特殊关键字处理
    def teshu_value(self,key,key_name,result,num,numx,numy,max_numx,max_numy):
        if key_name == '单位名称':
            value = '第一中标候选人'
            re_text = '项目负责人|项目经理|标段|排序|中标报价'
            return self.teshu_value1(key,key_name,result,num,numx,numy,max_numx,max_numy,value,re_text)
        if key_name == '名称':
            value = '第一中标候选人'
            re_text = '中标候选人排序|投标报价|排序'
            return self.teshu_value1(key, key_name, result, num, numx, numy, max_numx, max_numy, value, re_text)
        if key_name == '姓名':
            value = '项目负责人'
            re_text = '拟任项目负责人'
            return self.teshu_value1(key, key_name, result, num, numx, numy, max_numx, max_numy, value, re_text)
        return False

    # 特殊关键字处理 1-1
    def teshu_value1(self,key,key_name,result,num,numx,numy,max_numx,max_numy,value,re_text):
        # 向右
        x = numx
        y = numy
        while True:
            x += 1
            zz = self.teshu_value2(result,num,numx,numy,max_numx,max_numy,value,re_text,x,y,1)
            if zz != False and zz != True:
                return zz
            if zz == True:
                break
        # 向左
        x = numx
        y = numy
        while True:
            x -= 1
            zz = self.teshu_value2(result, num, numx, numy, max_numx, max_numy, value, re_text, x, y, 1)
            if zz != False and zz != True:
                return zz
            if zz == True:
                break
        # 向上
        x = numx
        y = numy
        while True:
            y -= 1
            zz = self.teshu_value2(result, num, numx, numy, max_numx, max_numy, value, re_text, x, y, 2)
            if zz != False and zz != True:
                return zz
            if zz == True:
                break
        # 向下
        x = numx
        y = numy
        while True:
            y += 1
            zz = self.teshu_value2(result, num, numx, numy, max_numx, max_numy, value, re_text, x, y, 2)
            if zz != False and zz != True:
                return zz
            if zz == True:
                break
        return False

    # 特殊关键字处理 1-2
    def teshu_value2(self,result,num,numx,numy,max_numx,max_numy,value,re_text,x,y,is_num):
        if is_num == 1:
            if x >= max_numx or x < 0:
                return True
            if result[num][numy][x] == result[num][numy][numx]:
                return False
            if re.search(re_text, result[num][numy][x]):
                return value
            if result[num][numy][x] != result[num][numy][numx]:
                return True
        elif is_num == 2:
            if y >= max_numy or y < 0:
                return True
            if result[num][y][numx] == result[num][numy][numx]:
                return False
            if re.search(re_text, result[num][y][numx]):
                return value
            if result[num][y][numx] != result[num][numy][numx]:
                return True


    # 联系方式等信息处理规则
    def contact_value1(self,key,key_name,key_listv,result,num,numx,numy):
        yz_re = '(业主|项目)(信息|名称|联系人|地址|联系电话|传真|电子签章|联系人电话|电子邮箱)'
        dl_re = '招标代理单位(信息|名称|联系人|地址|联系电话|传真|电子签章|联系人电话|电子邮箱)'
        # 向左
        x = numx
        while True:
            x -= 1
            if x < 0:
                break
            if result[num][numy][numx] not in result[num][numy][x]:
                if result[num][numy][x] in key:
                    if re.search(yz_re,key[result[num][numy][x]][0]):
                        zz = '业主' + key[key_name][0]
                        return zz
                    if re.search(dl_re,key[result[num][numy][x]][0]):
                        zz = '招标代理单位' + key[key_name][0]
                        return zz

        # 向上
        y = numy
        while True:
            y -= 1
            if y < 0:
                break
            if result[num][y][numx] in key:
                if re.search(yz_re, key[result[num][y][numx]][0]):
                    zz = '业主'+key[key_name][0]
                    return zz
                if re.search(dl_re, key[result[num][y][numx]][0]):
                    zz = '招标代理单位' + key[key_name][0]
                    return zz

        return False

    # 向右获取特殊处理
    # 向右一个单元格内数据跟当前单元格数据一致 那么继续向右
    def right_value1(self,key,key_name,key_listv,result,num,max_numx,numx,numy):
        x = numx
        while True:
            x += 1
            # 预防数组超出下限
            if x >= max_numx:
                return False
            if result[num][numy][numx] == result[num][numy][x] or result[num][numy][x] == '':
                continue
            if result[num][numy][x] in key:
                return False
            key_listv[key_name].append([result[num][numy][x],x,numy,key[key_name][0]])
            break

        return key_listv


    # 向右一个单元格内数据跟当前单元格内数据一致
    # 正常向下提取
    # 处理规则
    def portrait_value2(self,key,key_name,key_listv,result,num,i,numx,numy,s_h):
        y = numy + 1
        if self.len_list(result[num][y]) != self.len_list(result[num][y-1]):
            numx -= s_h
        while True:
            # 预防数组超出下限
            if y >= len(i):
                break
            # 判断当前数据是否为关键字
            if result[num][y][numx] in key or self.special(result[num][y][numx]):
                break
            key_listv[key_name].append([result[num][y][numx],numx,y,key[key_name][0]])
            y = y + 1
        return key_listv

    # 判断当前值是否是特殊处理关键字
    def special(self,value):
        retext = list(self.super_dict.keys())
        for i in retext:
            if re.search(i, value):
                return True
        return False


    # 返回list长度 不计算△
    def len_list(self,list):
        list_len = sum([Counter(list)[i] if i != '△' else 0 for i in Counter(list)])
        return list_len


    def html_handel(self):
        self.html = self.html.replace('&nbsp;', '')

    def main(self):
        self.html_handel()
        result = self.read_html_table(self.html)
        result_copy = []
        for i in result:
            result_copy.append(result[i])
        result = result_copy
        result_copy = []
        key = {} # 所需要的key标签
        key['a'] = []
        key['b'] = []
        key_name_list = []
        for i in range(0, len(result)):
            for c in range(0, len(result[i])):
                for n in range(0, len(result[i][c])):
                    key_name = result[i][c][n]
                    company = ''
                    front_company = ''
                    if re.findall(r'亿|万|%|分', key_name):
                        obj = re.search('（[^）]*?([亿万分%])[^（]*?）', key_name)
                        if obj:
                            company = '（'+obj.group(1)+'）'

                    key_name = self.replace_word(result[i][c][n])
                    if key_name in self.config_dict:
                        result[i][c][n] = key_name
                        if key_name not in key:
                            key[key_name] = []
                            key['a'].append(key_name)
                            key[key_name].append(front_company + self.config_dict[key_name] + company)
                    else:
                        if key_name not in key:
                            key['b'].append(result[i][c][n])
        key_list,is_key = self.obtain_html_tablev(key,result)
        return key_list,is_key

    def replace_word(self,word):
        if word == '':
            return word
        word = word.replace('?', '？')
        word = word.replace('(', '（')
        word = word.replace(')', '）')
        word = word.replace(':', '：')
        word = word.replace(' ','')
        word = word.replace('？','')
        word = word.replace('*', '')
        key = True
        while True:
            obj = re.search('（(\d+)分）$', word)
            if obj:
                key = False
                word = word.replace(obj.group(1), '')

            obj = re.search(r'（([^（]*?)）$', word)
            if obj:
                key = False
                tt = obj.group(1)
                word = word.replace('（' + tt + '）', '')
            sub_list = ['？', ':', '：', '/', '\\', '>', '<', '，', '。', '、', ';', '￥', '|']
            if word == '':
                return word
            if word[0] in sub_list:
                key = False
                word = word[1:]
            if word == '':
                return word
            if word[-1] in sub_list:
                key = False
                word = word[:-1]
            if key:
                break
            else:
                key = True

        ls = ['\d{1,2}[.、]', '[一二三四五六七八九十]{1,2}[.、]', '（[一二三四五六七八九十]）', '（\d{1,2}）']
        ls = ['^' + i + '(.*)' for i in ls]
        for i in ls:
            word = re.sub(i, '\\1', word)
        return word

if __name__ == '__main__':
    with Db('dispose') as conn:
        html = open(r'C:\Users\Administrator\Desktop\table_easy\table16.html',encoding='utf-8')
        text = html.read()
        html.close()
        cusor = conn.cursor()
        params = {'conn':conn,
                  'cursor':cusor}
        conf = Conf(**params).main()
        super_dict = conf['super_dict']
        all_dict = conf['all_dict']

        params = {
            'html' : text,
            'conf' : conf
        }
        t = Keyvaluetable(**params)
        key_list,is_key = t.main()
        print(key_list)
        print('-'*50)
        print(is_key)
